package cn.golxen.rsms.service.impl;

import cn.golxen.rsms.bean.bo.*;
import cn.golxen.rsms.bean.entity.PayLog;
import cn.golxen.rsms.bean.entity.PayRegister;
import cn.golxen.rsms.commons.utils.CommonsUtils;
import cn.golxen.rsms.commons.utils.LocalDateTimeUtils;
import cn.golxen.rsms.commons.utils.WeChatPayV2Utils;
import cn.golxen.rsms.commons.utils.YmlUtils;
import cn.golxen.rsms.config.WechatPayConfig;
import cn.golxen.rsms.exception.exceptionClass.PayException;
import cn.golxen.rsms.mapper.PayMapper;
import cn.golxen.rsms.redis.PayRedis;
import cn.golxen.rsms.redis.StoreRedis;
import cn.golxen.rsms.service.CustomerService;
import cn.golxen.rsms.service.GoodsService;
import cn.golxen.rsms.service.LogService;
import cn.golxen.rsms.service.PayService;
import com.alibaba.fastjson.JSONObject;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.wechat.pay.java.core.Config;


import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;

import com.wechat.pay.java.service.payments.nativepay.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class PayServiceImpl implements PayService {

    @Autowired
    GoodsService goodsService;
    @Autowired
    LogService logService;
    @Autowired
    PayMapper payMapper;
    @Autowired
    PayRedis payRedis;
    @Autowired
    StoreRedis storeRedis;

    @Autowired
    @Qualifier(value = "taskExecutor")
    private ThreadPoolTaskExecutor poolTaskExecutor;
    @Autowired
    CustomerService customerService;



    public PlaceOrderBo placeOrderByNative(PlaceOrderBo placeOrderBo) {

        Config config =WechatPayConfig.wechatPayConfigV3Map.get(placeOrderBo.getStoreId());
        // 使用自动更新平台证书的RSA配置,自动注入变量名为config
        // 一个商户号只能初始化一个配置，否则会因为重复的下载任务报错
        //使用微信支付SDK调用微信支付Native模式接口
        NativePayService service = new NativePayService.Builder().config(config).build();
        //设置对应参数
        // request.setXxx(val)设置所需参数
        PrepayRequest request = new PrepayRequest();

        //公众号开发者ID
        request.setAppid(YmlUtils.getString("wechat.appid"));
        //商户号参数
        request.setMchid(String.valueOf(placeOrderBo.getStoreId()));
        //订单标题
        request.setDescription("rsms收银-微信支付Native下单");
        //订单详情
//        Detail detail=new Detail();
//        List<GoodsDetail> goodsDetails=new LinkedList<>();
//        GoodsDetail goodsDetail=new GoodsDetail();
//        goodsDetail.setMerchantGoodsId("test");
//        goodsDetail.setQuantity(1);
//        goodsDetail.setUnitPrice(10);
//        goodsDetails.add(goodsDetail);
//        detail.setGoodsDetail(goodsDetails);
//        request.setDetail(detail);
        //优惠处理
        double totalD=placeOrderBo.getTotal()*100;
        int totalI= (int) totalD;
        int fullDecrCost=0;
        int discountCost=0;
        int bundleSalesCost=0;
        for (AddOrOutGoodsNumBo addOrOutGoodsNumBo:placeOrderBo.getDetailObject()){
            String attachStr=storeRedis.getStoreOffers(addOrOutGoodsNumBo.getCode(),placeOrderBo.getStoreId());
            if (attachStr!=null){
                StoreOffersAttachBo attachBo=JSONObject.parseObject(attachStr,StoreOffersAttachBo.class);
                int total= (int) (addOrOutGoodsNumBo.getNum()*addOrOutGoodsNumBo.getPrice()*100);
                if (attachBo.getAttach().contains("赠送")){
                    for (String code:attachBo.getBundleSales()){
                        double cost=(int)(goodsService.getGoodsInfo2(code,placeOrderBo.getStoreId()).getCost()*100);
                        bundleSalesCost+=cost;
                    }
                }
                if (attachBo.getAttach().contains("打折")){
                    int cost= (int) (total-total*attachBo.getDiscount());
                    total*=attachBo.getDiscount();
                    totalI-=cost;
                    discountCost+=cost;
                }
                if (attachBo.getAttach().contains("满减")){
                    if (total>=attachBo.getFullDecr()*100){
                        totalI-=(int)(attachBo.getFullDecrCost()*100);
                        fullDecrCost+=(int)(attachBo.getFullDecrCost()*100);
                    }
                }
            }
        }
        String attachStr=storeRedis.getStoreOffersGlobal(placeOrderBo.getStoreId());
        if (attachStr!=null){
            StoreOffersAttachBo attachBo=JSONObject.parseObject(attachStr,StoreOffersAttachBo.class);
            if (attachBo.getAttach().contains("赠送")){
                for (String code:attachBo.getBundleSales()){
                    double cost=(int)(goodsService.getGoodsInfo2(code,placeOrderBo.getStoreId()).getCost()*100);
                    bundleSalesCost+=cost;
                }
            }
            if (attachBo.getAttach().contains("打折")){
                int cost= (int) (totalI-totalI*attachBo.getDiscount());
                totalI-=cost;
                discountCost+=cost;
            }
            if (attachBo.getAttach().contains("满减")){
                if (totalI>=attachBo.getFullDecr()*100){
                    totalI-=(int)(attachBo.getFullDecrCost()*100);
                    fullDecrCost+=(int)(attachBo.getFullDecrCost()*100);
                }
            }
        }
        if (bundleSalesCost!=0)
            placeOrderBo.setAttach("赠送="+(double)bundleSalesCost/100);
        if (discountCost!=0)
            placeOrderBo.setAttach(placeOrderBo.getAttach()+"|打折="+(double)discountCost/100);
        if (fullDecrCost!=0)
            placeOrderBo.setAttach(placeOrderBo.getAttach()+"|满减="+(double)fullDecrCost/100);
        //订单金额
//        double totalD=placeOrderBo.getTotal()*100;
//        Integer totalI= (int) totalD;
        Amount amount=new Amount();
        amount.setTotal(totalI);
        request.setAmount(amount);
        //备注
        request.setAttach(placeOrderBo.getAttach());
        //订单号商店id+时间戳
        String outTradeNo=placeOrderBo.getStoreId()+""+System.currentTimeMillis();
        request.setOutTradeNo(outTradeNo);
        //订单过期时间
//        request.setTimeExpire(LocalDateTimeUtils.getWeChatPayTimeExpire(1));

//        request.setGoodsTag("优惠标记");
        //订单回调通知地址
        request.setNotifyUrl(YmlUtils.getString("wechat.notify-url"));
        //商店信息
//        request.setSceneInfo(new SceneInfo());
        //统一下单
        PrepayResponse response = service.prepay(request);
        log.info("支付二维码："+response.getCodeUrl());

        placeOrderBo.setTotal((double)totalI/100);
        placeOrderBo.setOrderId(outTradeNo);
        LocalDateTime createTime=LocalDateTimeUtils.getLocalDateTime();
        placeOrderBo.setCreateTime(createTime);
        placeOrderBo.setEndTime(createTime.plusHours(1));
        placeOrderBo.setCodeUrl(response.getCodeUrl());
        placeOrderBo.setPayment("Native扫码支付");
        payRedis.placeOrderByNative(placeOrderBo,placeOrderBo.getOrderId());



        return placeOrderBo;
    }

    @Override
    public String queryOrder(PlaceOrderBo placeOrderBo) {
        try {
            Config config =WechatPayConfig.wechatPayConfigV3Map.get(placeOrderBo.getStoreId());
            NativePayService service = new NativePayService.Builder().config(config).build();
            QueryOrderByOutTradeNoRequest outTradeNoRequest=new QueryOrderByOutTradeNoRequest();
            outTradeNoRequest.setOutTradeNo(placeOrderBo.getOrderId());
            outTradeNoRequest.setMchid(String.valueOf(placeOrderBo.getStoreId()));

            String state="";

            Transaction responseTransaction=service.queryOrderByOutTradeNo(outTradeNoRequest);
            log.info("订单"+responseTransaction.getOutTradeNo()+"状态："+responseTransaction.getTradeState().toString());
            state=responseTransaction.getTradeState().toString();
            if (!state.equals("NOTPAY")&&!state.equals("USERPAYING")){
                if (state.equals("SUCCESS")){
                    poolTaskExecutor.execute(()->{
                        placeOrderBo.setIsDone(1);
                        placeOrderBo.setCustomerId(responseTransaction.getPayer().getOpenid());
                        payRedis.queryOrder(placeOrderBo.getOrderId());
                        goodsService.outGoodsNum(placeOrderBo.getDetailObject());
                        logService.addGoodsLogListByObject(placeOrderBo,"售出");
                        logService.updateOrderIsDone(placeOrderBo.getOrderId(),placeOrderBo.getCustomerId(),placeOrderBo.getIsDone());
                        customerService.customerPayHandle(responseTransaction.getPayer().getOpenid(),placeOrderBo.getStoreId(),
                                placeOrderBo.getDetailObject());
                    });
                }
                else
                    payRedis.queryOrder(placeOrderBo.getOrderId());
            }

            return state;
        }catch (Exception e){
            e.printStackTrace();
            throw new PayException();
        }
    }

    @Override
    public List<PlaceOrderBo> getPayingCodeList(int storeId) {
        List<PlaceOrderBo> placeOrderBoList=new ArrayList<>();
        Set<String> payingOrderList= payRedis.getPayingOrderList(storeId);
        payingOrderList.forEach((value)->{
            placeOrderBoList.add(payRedis.placeOrderByNative(null,value.split("::")[1]));
        });
        return placeOrderBoList;
    }

    @Override
    public String placeOrderByAuthCode(PlaceOrderByAuthCodeBo placeOrderBo) {


        WeChatPayV2Bo weChatPayV2Bo = new WeChatPayV2Bo();
        weChatPayV2Bo.setAuth_code(placeOrderBo.getAuthCode());
        weChatPayV2Bo.setAppid(YmlUtils.getString("wechat.appid"));
        weChatPayV2Bo.setMch_id(String.valueOf(placeOrderBo.getStoreId()));
        weChatPayV2Bo.setNonce_str(String.valueOf(System.currentTimeMillis()));
        weChatPayV2Bo.setBody("rsms收银-微信支付款码支付");
        weChatPayV2Bo.setAttach(placeOrderBo.getAttach());
        weChatPayV2Bo.setApi_key(WechatPayConfig.wechatPayConfigV2Map.get(placeOrderBo.getStoreId()));
        String outTradeNo=placeOrderBo.getStoreId()+""+System.currentTimeMillis();
        weChatPayV2Bo.setOut_trade_no(outTradeNo);
        double totalD=placeOrderBo.getTotal()*100;
        int totalI= (int) totalD;
        int fullDecrCost=0;
        int discountCost=0;
        int bundleSalesCost=0;
        for (AddOrOutGoodsNumBo addOrOutGoodsNumBo:placeOrderBo.getDetailObject()){
            String attachStr=storeRedis.getStoreOffers(addOrOutGoodsNumBo.getCode(),placeOrderBo.getStoreId());
            if (attachStr!=null){
                StoreOffersAttachBo attachBo=JSONObject.parseObject(attachStr,StoreOffersAttachBo.class);
                int total= (int) (addOrOutGoodsNumBo.getNum()*addOrOutGoodsNumBo.getPrice()*100);
                if (attachBo.getAttach().contains("赠送")){
                    for (String code:attachBo.getBundleSales()){
                        double cost=(int)(goodsService.getGoodsInfo2(code,placeOrderBo.getStoreId()).getCost()*100);
                        bundleSalesCost+=cost;
                    }
                }
                if (attachBo.getAttach().contains("打折")){
                    int cost= (int) (total-total*attachBo.getDiscount());
                    total*=attachBo.getDiscount();
                    totalI-=cost;
                    discountCost+=cost;
                }
                if (attachBo.getAttach().contains("满减")){
                    if (total>=attachBo.getFullDecr()*100){
                        totalI-=(int)(attachBo.getFullDecrCost()*100);
                        fullDecrCost+=(int)(attachBo.getFullDecrCost()*100);
                    }
                }
            }
        }
        String attachStr=storeRedis.getStoreOffersGlobal(placeOrderBo.getStoreId());
        if (attachStr!=null){
            StoreOffersAttachBo attachBo=JSONObject.parseObject(attachStr,StoreOffersAttachBo.class);
            if (attachBo.getAttach().contains("赠送")){
                for (String code:attachBo.getBundleSales()){
                    double cost=(int)(goodsService.getGoodsInfo2(code,placeOrderBo.getStoreId()).getCost()*100);
                    bundleSalesCost+=cost;
                }
            }
            if (attachBo.getAttach().contains("打折")){
                int cost= (int) (totalI-totalI*attachBo.getDiscount());
                totalI-=cost;
                discountCost+=cost;
            }
            if (attachBo.getAttach().contains("满减")){
                if (totalI>=attachBo.getFullDecr()*100){
                    totalI-=(int)(attachBo.getFullDecrCost()*100);
                    fullDecrCost+=(int)(attachBo.getFullDecrCost()*100);
                }
            }
        }
        if (bundleSalesCost!=0)
            placeOrderBo.setAttach("赠送="+(double)bundleSalesCost/100);
        if (discountCost!=0)
            placeOrderBo.setAttach(placeOrderBo.getAttach()+"|打折="+(double)discountCost/100);
        if (fullDecrCost!=0)
            placeOrderBo.setAttach(placeOrderBo.getAttach()+"|满减="+(double)fullDecrCost/100);

        weChatPayV2Bo.setTotal_fee(String.valueOf(totalI));
        weChatPayV2Bo.setAttach(placeOrderBo.getAttach());
        placeOrderBo.setTotal((double)totalI/100);
        placeOrderBo.setOrderId(outTradeNo);
        placeOrderBo.setCreateTime(LocalDateTimeUtils.getLocalDateTime());
        placeOrderBo.setPayment("付款码支付");
        Map<String, String> map = new HashMap<>();
        map = CommonsUtils.objectToMapOnString(weChatPayV2Bo);
        String res="支付失败";
        try {
            String sign= WXPayUtil.generateSignature(map, weChatPayV2Bo.getApi_key(), WXPayConstants.SignType.MD5);
            map.put("sign",sign);
            map.remove("api_key");
            String xmlBody = WXPayUtil.generateSignedXml(map, weChatPayV2Bo.getApi_key());
            log.info("placeOrderByAuthCode信息----XML：" + xmlBody);

            res= WeChatPayV2Utils.httpsRequest("https://api.mch.weixin.qq.com/pay/micropay","POST",xmlBody);
        } catch (Exception e) {
            e.printStackTrace();
            throw new PayException();
        }
        log.info(res);

        String resultCode="FAIL";
        try {
            Map<String,String> resultMap=WXPayUtil.xmlToMap(res);
            resultCode=resultMap.get("result_code");
            logService.addPayLog(placeOrderBo);
            if (resultCode.equals("SUCCESS")){
                poolTaskExecutor.execute(()->{
                    placeOrderBo.setIsDone(1);
                    placeOrderBo.setCustomerId(resultMap.get("openid"));
                    goodsService.outGoodsNum(placeOrderBo.getDetailObject());
                    logService.updateOrderIsDone(placeOrderBo.getOrderId(),placeOrderBo.getCustomerId(),placeOrderBo.getIsDone());
                    customerService.customerPayHandle(resultMap.get("openid"),placeOrderBo.getStoreId(),
                            placeOrderBo.getDetailObject());
                });

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return resultCode;
    }

    @Override
    public int addPayRegister(PayRegister payRegister) {
        //将挂单详情转为json字符串存储
        payRegister.setDetailStr(JSONObject.toJSONString(payRegister.getDetailObject()));
        payRegister.setCreateTime(LocalDateTimeUtils.getLocalDateTime());
        Double total=0.0;
        for (PayRegisterDetailBo payRegisterDetailBo: payRegister.getDetailObject()){
            total+=payRegisterDetailBo.getTotal();
        }
        payRegister.setTotal(total);
        return payMapper.addPayRegister(payRegister);
    }

    @Override
    public int delPayRegister(List<PayRegister> payRegisters) {
        return payMapper.delPayRegister(payRegisters,payRegisters.get(0).getStoreId());
    }

    @Override
    public List<PayRegister> getPayRegister(int storeId) {
        List<PayRegister> payRegisters=payMapper.getPayRegister(storeId);

        for (PayRegister payRegister:payRegisters){
            payRegister.setDetailObject(JSONObject.parseObject(payRegister.getDetailStr(),List.class));
        }
        return payRegisters;
    }

    @Override
    public PayLog placeOrderByQuick(PayLog placeOrderBo) {
        double totalD=placeOrderBo.getTotal()*100;
        int totalI= (int) totalD;
        int fullDecrCost=0;
        int discountCost=0;
        int bundleSalesCost=0;
        for (AddOrOutGoodsNumBo addOrOutGoodsNumBo:placeOrderBo.getDetailObject()){
            String attachStr=storeRedis.getStoreOffers(addOrOutGoodsNumBo.getCode(),placeOrderBo.getStoreId());
            if (attachStr!=null){
                StoreOffersAttachBo attachBo=JSONObject.parseObject(attachStr,StoreOffersAttachBo.class);
                int total= (int) (addOrOutGoodsNumBo.getNum()*addOrOutGoodsNumBo.getPrice()*100);
                if (attachBo.getAttach().contains("赠送")){
                    for (String code:attachBo.getBundleSales()){
                        double cost=(int)(goodsService.getGoodsInfo2(code,placeOrderBo.getStoreId()).getCost()*100);
                        bundleSalesCost+=cost;
                    }
                }
                if (attachBo.getAttach().contains("打折")){
                    int cost= (int) (total-total*attachBo.getDiscount());
                    total*=attachBo.getDiscount();
                    totalI-=cost;
                    discountCost+=cost;
                }
                if (attachBo.getAttach().contains("满减")){
                    if (total>=attachBo.getFullDecr()*100){
                        totalI-=(int)(attachBo.getFullDecrCost()*100);
                        fullDecrCost+=(int)(attachBo.getFullDecrCost()*100);
                    }
                }
            }
        }
        String attachStr=storeRedis.getStoreOffersGlobal(placeOrderBo.getStoreId());
        if (attachStr!=null){
            StoreOffersAttachBo attachBo=JSONObject.parseObject(attachStr,StoreOffersAttachBo.class);
            if (attachBo.getAttach().contains("赠送")){
                for (String code:attachBo.getBundleSales()){
                    double cost=(int)(goodsService.getGoodsInfo2(code,placeOrderBo.getStoreId()).getCost()*100);
                    bundleSalesCost+=cost;
                }
            }
            if (attachBo.getAttach().contains("打折")){
                int cost= (int) (totalI-totalI*attachBo.getDiscount());
                totalI-=cost;
                discountCost+=cost;
            }
            if (attachBo.getAttach().contains("满减")){
                if (totalI>=attachBo.getFullDecr()*100){
                    totalI-=(int)(attachBo.getFullDecrCost()*100);
                    fullDecrCost+=(int)(attachBo.getFullDecrCost()*100);
                }
            }
        }
        if (bundleSalesCost!=0)
            placeOrderBo.setAttach("赠送="+(double)bundleSalesCost/100);
        if (discountCost!=0)
            placeOrderBo.setAttach(placeOrderBo.getAttach()+"|打折="+(double)discountCost/100);
        if (fullDecrCost!=0)
            placeOrderBo.setAttach(placeOrderBo.getAttach()+"|满减="+(double)fullDecrCost/100);

        placeOrderBo.setTotal((double)totalI/100);
        String outTradeNo=placeOrderBo.getStoreId()+""+System.currentTimeMillis();
        placeOrderBo.setOrderId(outTradeNo);
        placeOrderBo.setCreateTime(LocalDateTimeUtils.getLocalDateTime());
        placeOrderBo.setIsDone(1);
        goodsService.outGoodsNum(placeOrderBo.getDetailObject());
        return placeOrderBo;
    }

    @Override
    public PayLog getLastOrderByDone(int storeId) {
        return logService.getLastOrderByDone(storeId);
    }


}
